﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Linq;
using Abp.Organizations;
using Abp.Runtime.Caching;
using KelonProud.Administration.Domain.Authorization;
using KelonProud.Administration.Dtos;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace KelonProud.Administration.Managers.Authorization
{
    public class UserManager : AbpUserManager<Role, User>
    {
        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<UserRole, long> _userRoleRepository;
        private readonly ICacheManager _cacheManager;
        public UserStore UserStore { get; }

        public UserManager(
            RoleManager roleManager,
            UserStore store,
            IOptions<IdentityOptions> optionsAccessor,
            IPasswordHasher<User> passwordHasher,
            IEnumerable<IUserValidator<User>> userValidators,
            IEnumerable<IPasswordValidator<User>> passwordValidators,
            ILookupNormalizer keyNormalizer,
            IdentityErrorDescriber errors,
            IServiceProvider services,
            ILogger<UserManager<User>> logger,
            IPermissionManager permissionManager,
            IUnitOfWorkManager unitOfWorkManager,
            ICacheManager cacheManager,
            IRepository<OrganizationUnit, long> organizationUnitRepository,
            IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
            IOrganizationUnitSettings organizationUnitSettings,
            ISettingManager settingManager, IRepository<User, long> userRepository, ICacheManager cacheManager1, UserStore userStore, IRepository<UserRole, long> userRoleRepository)
            : base(
                roleManager,
                store,
                optionsAccessor,
                passwordHasher,
                userValidators,
                passwordValidators,
                keyNormalizer,
                errors,
                services,
                logger,
                permissionManager,
                unitOfWorkManager,
                cacheManager,
                organizationUnitRepository,
                userOrganizationUnitRepository,
                organizationUnitSettings,
                settingManager)
        {
            _userRepository = userRepository;
            _cacheManager = cacheManager1;
            UserStore = userStore;
            _userRoleRepository = userRoleRepository;
        }


        public UserOutputDto CurretUserOutPut
        {
            get
            {
                return _cacheManager.GetCache("sysChche")
                    .Get("currentUser", () => UserStore.UserList.First(f => f.Id == AbpSession.UserId).MapTo<UserOutputDto>());
            }
        }

        public User CurrentUser => _userRepository.Get(AbpSession.UserId.ToInt32());

        public List<UserOutputDto> UserCache
        {
            get
            {
                var userList = Users.ToList();
                return _cacheManager
                    .GetCache("sysChche")
                    .Get("users", () => userList.Select(s => s.MapTo<UserOutputDto>()).ToList());
            }
        }

        public virtual User GetById(long id)
        {
            return Users.FirstOrDefault(f => f.Id==id);
        }


        //设置用户角色
        public virtual async Task<IdentityResult> SetRoles(long userId, string[] roleIds)
        {
            var user = await GetUserByIdAsync(userId);

            //Remove from removed roles
            if (user.Roles != null)
            {
                foreach (var userRole in user.Roles.ToList())
                {
                    if (roleIds.All(a => a != userRole.RoleId.ToString()))
                    {
                        _userRoleRepository.Delete(userRole);
                    }
                }
            }

            //Add to added roles
            foreach (var roleId in roleIds)
            {
                if (user.Roles == null)
                    user.Roles = new List<UserRole>();

                if (user.Roles.All(ur => ur.RoleId.ToString() != roleId))
                {
                    _userRoleRepository.Insert(new UserRole()
                    {
                        UserId = userId,
                        RoleId = roleId.ToInt32(0)
                    });
                }
            }

            return IdentityResult.Success;
        }

        public long CreateUser(User user)
        {
           return _userRepository.InsertAndGetId(user);
        }

        public long UpdateUser(User user)
        {
            return _userRepository.InsertOrUpdateAndGetId(user);
        }
    }

    public class UserStore : AbpUserStore<Role, User>
    {
        public UserStore(
            IUnitOfWorkManager unitOfWorkManager,
            IRepository<User, long> userRepository,
            IRepository<Role> roleRepository,
            IAsyncQueryableExecuter asyncQueryableExecuter,
            IRepository<UserRole, long> userRoleRepository,
            IRepository<UserLogin, long> userLoginRepository,
            IRepository<UserClaim, long> userClaimRepository,
            IRepository<UserPermissionSetting, long> userPermissionSettingRepository)
            : base(
                unitOfWorkManager,
                userRepository,
                roleRepository,
                asyncQueryableExecuter,
                userRoleRepository,
                userLoginRepository,
                userClaimRepository,
                userPermissionSettingRepository)
        {
        }

        public IEnumerable<User> UserList => UserRepository.GetAllList();
    }


}
